/**
 * Copyright (c) 2016 ShopJsp. All Rights Reserved.
 * ============================================================================
 * 版权所有 2011 - 今 北京华宇盈通科技有限公司，并保留所有权利。
 * ----------------------------------------------------------------------------
 * 提示：在未取得SHOPJSP商业授权之前，您不能将本软件应用于商业用途，否则SHOPJSP将保留追究的权力。
 * ----------------------------------------------------------------------------
 * 官方网站：http://www.shopjsp.com
 * ============================================================================
 */
package com.hyyt.shopjsp.shiro.filter;

import com.hyyt.shopjsp.util.common.LoggerUtils;
import com.hyyt.shopjsp.util.common.StringStaticKey;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * Copyright (c) 2016 ShopJsp. All Rights Reserved.
 * ============================================================================
 * 版权所有 2011 - 今 北京华宇盈通科技有限公司，并保留所有权利。
 * ----------------------------------------------------------------------------
 * 提示：在未取得SHOPJSP商业授权之前，您不能将本软件应用于商业用途，否则SHOPJSP将保留追究的权力。
 * ----------------------------------------------------------------------------
 * 官方网站：http://www.shopjsp.com
 * ============================================================================
 * 权限校验 Filter
 * @author CuiYS on 2016/10/27 0027上午 11:31.
 */
public class PermissionFilter extends AccessControlFilter {

    /**
     * 权限验证
     *      如果实现自动分配，使用该代码可以进行调取：UserRealm.doGetAuthorizationInfo(PrincipalCollection principalCollection)方法验证授权
     *      // Subject currentUser = SecurityUtils.getSubject();
     *      // boolean bl = currentUser.isPermitted(userName);
     * @param
     * @return
     */
	@Override
	protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
		//先判断带参数的权限判断
		Subject subject = getSubject(request, response);
		if(null != mappedValue){
			String[] arra = (String[])mappedValue;
			for (String permission : arra) {
				if(subject.isPermitted(permission)){
					return Boolean.TRUE;
				}
			}
		}
		HttpServletRequest httpRequest = ((HttpServletRequest)request);
		/**
		 * 兼容项目不需要部署到root下，也可以正常运行，但是权限没设置目前必须到root 的URI，
		 * 原因：如果你把这个项目叫 shirodemo，那么路径就是 /shirodemo/xxxx.htm ，
         * 那另外一个使用，又叫shiro_demo,那么就要这么控制/shiro_demo/xxxx.htm
		 * 所以这里替换了一下，使用根目录开始的URI
		 */
		String uri = httpRequest.getRequestURI();//获取URI
		String basePath = httpRequest.getContextPath();//获取basePath
		if(null != uri && uri.startsWith(basePath)){
			uri = uri.replaceFirst(basePath, "");
			//截取过滤权限前缀 "/" 特殊符号，保留可以匹配权限校验的路径地址
			if(uri.startsWith("/")) {
                uri = uri.replaceFirst("/", "");
            }
		}
        String ignoreUrl = "";// 获取忽略拦截的URL
        // 获取忽略拦截的URL拓展名
        if (uri.lastIndexOf(".") >= 0) {
			ignoreUrl = uri.substring(uri.lastIndexOf("."));
            //判断请求路径包含.sjson和.inhtm的，不拦截，通过；.sjson 表示ajax调用，.inhtm页面内页使用，不进行权限拦截
            if (StringStaticKey.PURVIEW_AJAX_LAST_SUFFIX.equals(ignoreUrl) || StringStaticKey.PURVIEW_IN_HTML_LAST_SUFFIX.equals(ignoreUrl)) {
                return Boolean.TRUE;
            }
        }
		/**
         *  shiro 验证是否具备访问权限，校验后缀为 .htm 的路径
		 */
		if(subject.isPermitted(uri)){
			return Boolean.TRUE;
		}
        /**
         *  shiro 验证是否具备访Ajax请求问权限
         */
		if(ShiroFilterUtils.isAjax(request)){
			Map<String,String> resultMap = new HashMap<String, String>();
			LoggerUtils.info(getClass(), "当前用户没有登录，并且是Ajax请求！");
			resultMap.put("login_status", "300");
			resultMap.put("message", "当前用户没有登录！");//当前用户没有登录！
			ShiroFilterUtils.out(response, resultMap);
		}
		return Boolean.FALSE;
	}

	@Override
	protected boolean onAccessDenied(ServletRequest request,ServletResponse response) throws Exception {
		Subject subject = getSubject(request, response);
		if (null == subject.getPrincipal()) {//表示没有登录，重定向到登录页面
			saveRequest(request);
			WebUtils.issueRedirect(request, response, ShiroFilterUtils.LOGIN_URL);
		} else {
			if (StringUtils.hasText(ShiroFilterUtils.UNAUTHORIZED)) {//如果有未授权页面跳转过去
				WebUtils.issueRedirect(request, response, ShiroFilterUtils.UNAUTHORIZED);
			} else {//否则返回401未授权状态码
				WebUtils.toHttp(response).sendError(HttpServletResponse.SC_UNAUTHORIZED);
			}
		}
		return Boolean.FALSE;
	}

}
